package com.agan.limit.manager;

import com.agan.limit.aop.Limit;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.RateLimiter; // 引入 Guava RateLimiter，用于实现令牌桶限流
import lombok.extern.slf4j.Slf4j;

import java.util.Map;

/**
 * Guava 限流管理器实现类
 * 使用 Guava 的 RateLimiter 来实现限流功能
 * @author weicj
 * @since 2025.01.24
 */
@Slf4j
public class GuavaLimiter implements LimiterManager {

    /**
     * 不同的接口，不同的流量控制
     * map的key为 Limiter.key
     */
    private final Map<String, RateLimiter> limitMap = Maps.newConcurrentMap();

    // 尝试访问接口，利用 Guava 的 RateLimiter 实现限流
    @Override
    public boolean tryAccess(Limit limit) {
        //key作用：不同的接口，不同的流量控制
        String key = limit.key();
        // 获取 RateLimiter 实例，基于传入的 limiter 配置
        RateLimiter rateLimiter = null;
        //验证缓存是否有命中key
        if (!limitMap.containsKey(key)) {
            // 创建令牌桶
            rateLimiter = RateLimiter.create(limit.limitNum());
            limitMap.put(key, rateLimiter);
            log.debug("新建了令牌桶={}，容量={}",key,limit.limitNum());
        }
        rateLimiter = limitMap.get(key);
        // 拿令牌
        boolean acquire = rateLimiter.tryAcquire(limit.timeout(), limit.timeunit());
        // 拿不到命令，直接返回异常提示
        if (!acquire) {
            log.debug("令牌桶={}，获取令牌失败",key);
            return false;
        }
        // 返回访问是否成功，true 表示获取到许可，false 表示未能获取
        return true;
    }

}
